﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace yafc.Data
{
	// This can be a pattern:
	// 		Pool<TKey, TData>;
	//		Pool.TryGet(Key, Callback<TKey, TData>)
	//			Return true && invoke the callback indicating the data
	//			has been acquired or is being acquiring. TData is null 
	//			if the data is being acquired, or TData is the real data.
	//			Return false if the key/data is first being acquired and
	//			it's the caller's responsibility to acquire it and add it
	//			to the pool.
	//		Pool.Add(Key, Data)
	//			When some caller first acquiring the key/data now has the
	//			data, use this method to add it to the pool.

	static public class ImagePool
	{
		static Dictionary<string, Image> images = new Dictionary<string, Image>();
		static Dictionary<string, Action<string, Image>> loading = new Dictionary<string, Action<string, Image>>();

		static public bool TryGet(string Url, Action<string, Image> Callback)
		{
			Image image;
			if (images.TryGetValue(Url, out image))
			{
				Callback.Invoke(Url, image);
				return true;
			}
			Action<string, Image> preCallback;
			lock (loading)
			{
				if (loading.TryGetValue(Url, out preCallback))
				{
					// sb is doing the job now, get wait.
					loading[Url] += Callback;
					Callback.Invoke(Url, null);					// Tell requester not completed yet.
					return true;
				}
				else
				{
					// Tell the requester to do the job
					loading[Url] = Callback;
					return false;
				}
			}
		}
		static public bool Add(string Url, Image image)
		{
			if (images.ContainsKey(Url))
				return false;
			lock (images)
			{
				images[Url] = image;
			}

			if (loading.ContainsKey(Url))
			{
				Action<string, Image> callbacks = loading[Url];
				lock (loading)
					loading.Remove(Url);
				callbacks.Invoke(Url, image);
			}

			return true;
		}
	}
}
